{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7ce487ae-03b6-4220-8ca7-4cfbd0eeb5c9",
   "metadata": {},
   "source": [
    "## 中文命名实体识别（NER）\n",
    "\n",
    "模型: uer/roberta-base-finetuned-cluener2020-chinese\n",
    "\n",
    "框架: MindSpore + MindSpore NLP\n",
    "\n",
    "运行环境: 香橙派 AIpro（20T） + Ubuntu + MindSpore 2.6.0 + MindSpore NLP 0.4.1\n",
    "\n",
    "模型加载方式：本地加载\n",
    "\n",
    "任务目标: 实现中文命名实体识别，预测每个Token对应的实体类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "52475a08-6219-41c3-a8bb-097661f6ebf4",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] DEVICE(5565,e7ffc4728020,python):2025-07-30-18:02:10.394.469 [mindspore/ccsrc/utils/dlopen_macro.h:165] DlsymAscend] Dynamically load symbol aclprofGetSupportedFeaturesV2 failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libmsprofiler.so: undefined symbol: aclprofGetSupportedFeaturesV2\n",
      "[WARNING] DEVICE(5565,e7ffc4728020,python):2025-07-30-18:02:10.394.596 [mindspore/ccsrc/utils/dlopen_macro.h:165] DlsymAscend] Dynamically load symbol aclrtEventGetTimestamp failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclrtEventGetTimestamp\n",
      "/usr/local/miniconda3/lib/python3.9/site-packages/numpy/core/getlimits.py:499: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.\n",
      "  setattr(self, word, getattr(machar, word).flat[0])\n",
      "/usr/local/miniconda3/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.\n",
      "  return self._float_to_str(self.smallest_subnormal)\n",
      "/usr/local/miniconda3/lib/python3.9/site-packages/numpy/core/getlimits.py:499: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.\n",
      "  setattr(self, word, getattr(machar, word).flat[0])\n",
      "/usr/local/miniconda3/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.\n",
      "  return self._float_to_str(self.smallest_subnormal)\n",
      "[WARNING] ME(5565:255085698514976,MainProcess):2025-07-30-18:02:16.905.318 [mindspore/context.py:1402] For 'context.set_context', the parameter 'device_target' will be deprecated and removed in a future version. Please use the api mindspore.set_device() instead.\n",
      "[WARNING] ME(5565:255085698514976,MainProcess):2025-07-30-18:02:16.908.709 [mindspore/context.py:1402] For 'context.set_context', the parameter 'device_id' will be deprecated and removed in a future version. Please use the api mindspore.set_device() instead.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MindSpore 版本: 2.6.0\n",
      "当前运行设备: Ascend\n"
     ]
    }
   ],
   "source": [
    "import mindspore as ms\n",
    "\n",
    "print(f\"MindSpore 版本: {ms.__version__}\")\n",
    "print(f\"当前运行设备: {ms.get_context('device_target')}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebd71e07-1397-4235-be1c-641e70a18c4a",
   "metadata": {},
   "source": [
    "加载模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f4017b7f-5bd0-4bd1-a122-51bbc89747bf",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] ME(5565:255085698514976,MainProcess):2025-07-30-18:02:16.926.593 [mindspore/context.py:1402] For 'context.set_context', the parameter 'ascend_config' will be deprecated and removed in a future version. Please use the api mindspore.device_context.ascend.op_precision.precision_mode(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.op_precision_mode(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.matmul_allow_hf32(),\n",
      "                                                       mindspore.device_context.ascend.op_precision.conv_allow_hf32(),\n",
      "                                                       mindspore.device_context.ascend.op_tuning.op_compile() instead.\n",
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache /tmp/jieba.cache\n",
      "Loading model cost 2.121 seconds.\n",
      "Prefix dict has been built successfully.\n",
      "/home/HwHiAiUser/.local/lib/python3.9/site-packages/mindnlp/transformers/tokenization_utils_base.py:1526: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted, and will be then set to `False` by default. \n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "# 使用 Hugging Face Hub 上的模型加载方式\n",
    "from mindnlp.transformers import BertTokenizer, BertForTokenClassification\n",
    "\n",
    "# 指定 Hugging Face 上的模型 ID\n",
    "model_name = \"uer/roberta-base-finetuned-cluener2020-chinese\"\n",
    "\n",
    "# 从 Hugging Face Hub 网络加载 tokenizer 和模型\n",
    "tokenizer = BertTokenizer.from_pretrained(model_name)\n",
    "model = BertForTokenClassification.from_pretrained(model_name, from_pt=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07d8fac2-2356-4bb7-92cb-4fd9082a2d3c",
   "metadata": {},
   "source": [
    "定义标签映射"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4dfd9dea-101c-4e08-a27e-f96591fcbf8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "id2label = {\n",
    "    0: 'O',\n",
    "    1: 'B-address', 2: 'I-address',\n",
    "    3: 'B-book', 4: 'I-book',\n",
    "    5: 'B-company', 6: 'I-company',\n",
    "    7: 'B-game', 8: 'I-game',\n",
    "    9: 'B-government', 10: 'I-government',\n",
    "    11: 'B-movie', 12: 'I-movie',\n",
    "    13: 'B-name', 14: 'I-name',\n",
    "    15: 'B-organization', 16: 'I-organization',\n",
    "    17: 'B-position', 18: 'I-position',\n",
    "    19: 'B-scene', 20: 'I-scene'\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e74077ee-de54-4020-9c03-463de48ef415",
   "metadata": {},
   "source": [
    "推理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "37cefc7c-d3ce-4465-8e8b-9ad33b615b80",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from mindspore import Tensor\n",
    "\n",
    "def predict(text):\n",
    "    encoded = tokenizer(text, return_tensors='ms', padding='max_length', truncation=True, max_length=128)\n",
    "    input_ids = encoded['input_ids']\n",
    "    attention_mask = encoded['attention_mask']\n",
    "\n",
    "    outputs = model(input_ids=input_ids, attention_mask=attention_mask)\n",
    "    logits = outputs.logits.asnumpy()\n",
    "    preds = np.argmax(logits, axis=-1)[0]\n",
    "    tokens = tokenizer.convert_ids_to_tokens(input_ids[0].asnumpy().tolist())\n",
    "\n",
    "    results = []\n",
    "    for token, label_id in zip(tokens, preds):\n",
    "        if token in ['[PAD]', '[CLS]', '[SEP]']:\n",
    "            continue\n",
    "        label = id2label.get(label_id, 'O')\n",
    "        results.append({'token': token, 'entity': label})\n",
    "    return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8ec83653-5868-4353-b10e-d982233bf0f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "马 → B-name\n",
      "化 → I-name\n",
      "腾 → I-name\n",
      "是 → O\n",
      "腾 → B-company\n",
      "讯 → I-company\n",
      "公 → I-company\n",
      "司 → I-company\n",
      "的 → O\n",
      "创 → B-position\n",
      "始 → I-position\n",
      "人 → I-position\n",
      "之 → O\n",
      "一 → O\n",
      "， → O\n",
      "出 → O\n",
      "生 → O\n",
      "于 → O\n",
      "广 → B-address\n",
      "东 → I-address\n",
      "汕 → I-address\n",
      "头 → I-address\n"
     ]
    }
   ],
   "source": [
    "sample_text = '马化腾是腾讯公司的创始人之一，出生于广东汕头'\n",
    "output = predict(sample_text)\n",
    "for item in output:\n",
    "    print(f\"{item['token']} → {item['entity']}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
